encode decode
通常如果一樣東西需要編碼,說明這樣東西並不適合傳輸。原因多種多樣,如 Size 過大,包含隱私資料,對於 Url 來說,之所以要進行編碼,是因為 Url 中有些字元會引起歧義。
例如,url 引數字串中使用 key=value 鍵值對這樣的形式來傳參,鍵值對之間以&符號分隔,如/s?q=abc&ie=utf-8。如果你的 value 字串中包含了=或者&,那麼勢必會造成接收 Url 的伺服器解析錯誤,因此必須將引起歧義的&和=符號進行轉義,也就是對其進行編碼。
又如,url 的編碼格式採用的是 ASCII 碼,而不是 Unicode,這也就是說你不能在 Url 中包含任何非 ASCII 字元,例如中文。否則如果客戶端瀏覽器和服務端瀏覽器支援的字符集不同的情況下,中文可能會造成問題。
url 編碼的原則:就是使用安全的字元(沒有特殊用途或者特殊意義的可列印字元)去表示那些不安全的字元。 預備知識:URI 是統一資源標識的意思,通常我們所說的 URL 只是 URI 的一種。 典型 URL 的格式如下所示。下面提到的 URL 編碼,實際上應該指的是 URI 編碼。
foo://example.com:8042/over/there?name=ferret#nose
\__/ \_______________/\_________/\__________/\__/
| | | | |
scheme authority path query fragment
哪些字元需要編碼
RFC3986 文件規定,*URL 中只允許包含英文字母(a-zA-Z)、數字(0-9)、-_.~ 4 個特殊字元以及所有保留字元*。RFC3986 文件對 Url 的編解 碼問題做出了詳細的建議,指出了哪些字元需要被編碼才不會引起 Url 語義的轉變,以及對為什麼這些字元需要編碼做出了相應的解釋。
US-ASCII 字符集中沒有對應的可列印字元:Url 中只允許使用可列印字元。US-ASCII 碼中的 10-7F 位元組全都表示控制字元,這些字元都不能直接出現在 Url 中。同時,對於 80-FF 位元組(ISO-8859-1),由於已經超出了 US-ACII 定義的位元組範圍,因此也不可以放在 Url 中。
保留字元:URL 可以劃分成若干個元件,協議、主機、路徑等。有一些字元(:/?#[]@)是用作分隔不同元件的。
例如:冒號用於分隔協議和主機,/用於分隔主機和路徑,?用於分隔路徑和查詢引數,等等。還有一些字元(!$&'()*+,;=)用於在每個元件中起到分隔作用的,如=用於表示查詢引數中的鍵值對,&符號用於分隔查詢多個鍵值對。當元件中的普通資料包含這些特殊字元時,需要對其進行編碼。
RFC3986 中指定了以下字元為保留字元:! * ' ( ) ; : @ & = + $ , / ? # [ ]
不安全字元:還有一些字元,當他們直接放在 URL 中的時候,可能會引起解析程式的歧義。這些字元被視為不安全字元,原因有很多。
- 空格:url 在傳輸的過程,或者使用者在排版的過程,或者文字處理程式在處理 url 的過程,都有可能引入無關緊要的空格,或者將那些有意義的空格給去掉。
- 引號以及
<>:引號和尖括號通常用於在普通文字中起到分隔 url 的作用 - #:通常用於表示書籤或者錨點
- %:百分號本身用作對不安全字元進行編碼時使用的特殊字元,因此本身需要編碼
- |^[]`~:某一些閘道器或者傳輸代理會篡改這些字元
需要注意的是,對於 Url 中的合法字元,編碼和不編碼是等價的,但是對於上面提到的這些字元,如果不經過編碼,那麼它們有可能會造成 Url 語義的不同。因此對於 url 而言,只有普通英文字元和數字,特殊字元$-_.+!*'()還有保留字元,才能出現在未經編碼的 url 之中。其他字元均需要經過編碼之後才能出現在 Url 中。
但是由於歷史原因,目前尚存在一些不標準的編碼實現。例如對於符號,雖然 RFC3986 文件規定,對於波浪符號,不需要進行 Url 編碼,但是還是有很多老的閘道器或者傳輸代理會進行編碼。
URL 編碼遵循下列規則: 每對 name/value 由&;符分開;每對來自表單的 name/value 由=符分開。如果使用者沒有輸入值給這個 name,那麼這個 name 還是出現,只是無值。任何特殊的字元(就是那些不是簡單的七位 ASCII,如漢字)將以百分符%用十六進位制編碼,當然也包括象 =,&;,和 % 這些特殊的字元。其實 url 編碼就是一個字元 ascii 碼的十六進位制。不過稍微有些變動,需要在前面加上“%”。比如“\”,它的 ascii 碼是 92,92 的十六進位制是 5c,所以“\”的 url 編碼就是%5c。那麼漢字的 url 編碼呢?很簡單,看例子:“胡”的 ascii 碼是-17670,十六進位制是 BAFA,url 編碼是“%BA%FA”。
防止 sql 注入。URL 編碼平時是用不到的,因為 IE 會自動將輸入到位址列的非數字字母轉換為 url 編碼。曾有人提出資料庫名字裡帶上“#”以防止被下載,因為 IE 遇到#就會忽略後面的字母。破解方法很簡單——用 url 編碼%23 替換掉#。也可以使用 “雙 URL 編碼”